
`include "common_header.verilog"

//  *************************************************************************
//   File : pcs_tx_state_mc.v
//  *************************************************************************
//   This program is controlled by a written license agreement.
//   Unauthorized Reproduction or Use is Expressly Prohibited. 
// 
//  Copyright (c) 2005 Morethanip GmbH
//  info@morethanip.com
//  *************************************************************************
//  Version: $Id: pcs_tx_encoder.v,v 1.5 2011/08/31 13:10:45 dk Exp $ 
//  Author : Muhammad Anisur Rahman
//  *************************************************************************
//  Description:
// 
//  XGMII character to PCS code group Mapping
// 
//  *************************************************************************

module pcs_tx_encoder (

   reset,
   clk,
`ifdef USE_CLK_ENA
   clk_ena,
`endif    
   xgmii_txd_d,
   xgmii_txc_d,
   encode_col,
`ifdef MTIPXGXS_EEE_ENA
   encode_lpi,
   encode_lpi_rnd,
`endif
   encode_txd,
   encode_txc);

input   reset;
input   clk; 
`ifdef USE_CLK_ENA
input   clk_ena;        //  Enable clk
`endif
input   [31:0] xgmii_txd_d; 
input   [3:0] xgmii_txc_d; 
input   [2:0] encode_col; 
`ifdef MTIPXGXS_EEE_ENA
input         encode_lpi;       // encode LPI column
input   [1:0] encode_lpi_rnd;   // random lane for the LPI character
`endif
output  [31:0] encode_txd; 
output  [3:0] encode_txc; 

reg     [31:0] encode_txd; 
reg     [3:0] encode_txc; 

wire    [3:0] xgmii_termc;      // Control signal for terminate

wire    xgmiii_seq;             // Sequence should not be transmitted as data

`ifdef MTIPXGXS_EEE_ENA
wire    [2:0] lpi_sel;

assign lpi_sel = { encode_lpi, encode_lpi_rnd };        // combine enable with selector
`endif

parameter K_COL        = 3'b 000; 
parameter DATA_COL     = 3'b 001; 
parameter A_COL        = 3'b 010; 
parameter Q_COL        = 3'b 011; 
parameter RANDOM_R_COL = 3'b 100; 
parameter RANDOM_K_COL = 3'b 101; 
parameter RANDOM_A_COL = 3'b 110; 
parameter RANDOM_Q_COL = 3'b 111; 

// Control signals extracted from the Decoded data
// -----------------------------------------------                                                

assign xgmii_termc[0] = xgmii_txc_d[0] == 1'b 1 & xgmii_txd_d[7:0] == 8'h FD ? 1'b 1 : 1'b 0; 
assign xgmii_termc[1] = xgmii_txc_d[1] == 1'b 1 & xgmii_txd_d[15:8] == 8'h FD ? 1'b 1 : 1'b 0; 
assign xgmii_termc[2] = xgmii_txc_d[2] == 1'b 1 & xgmii_txd_d[23:16] == 8'h FD ? 1'b 1 : 1'b 0; 
assign xgmii_termc[3] = xgmii_txc_d[3] == 1'b 1 & xgmii_txd_d[31:24] == 8'h FD ? 1'b 1 : 1'b 0; 

assign xgmiii_seq = ((xgmii_txd_d[31:24] == 8'h 01 | xgmii_txd_d[31:24] == 8'h 02) & xgmii_txd_d[23:0] == 24'h 00009C & xgmii_txc_d == 4'b 0001) ? 1'b 1 : 1'b 0; 

always @(posedge reset or posedge clk)
   begin : process_1
   if (reset == 1'b 1)
      begin
      encode_txd <= 32'h 07070707;   
      encode_txc <= 4'b 1111;   
      end
   else
      begin
      
         `ifdef USE_CLK_ENA
            if(clk_ena == 1'b 1)
            begin
         `endif       
      
      case (encode_col)
      DATA_COL:
         begin
         if (xgmii_termc[0] == 1'b 1)
            begin

   // Termination on the Lane 0
   // -------------------------
   
            encode_txd[7:0]   <= xgmii_txd_d[7:0];   
            encode_txc[0]     <= xgmii_txc_d[0];   
            encode_txd[15:8]  <= 8'h BC;   
            encode_txc[1]     <= 1'b 1;   
            encode_txd[23:16] <= 8'h BC;   
            encode_txc[2]     <= 1'b 1;   
            encode_txd[31:24] <= 8'h BC;   
            encode_txc[3]     <= 1'b 1;   
            end
         else if (xgmii_termc[1] == 1'b 1 )
            begin

   // Termination on the Lane 1
   // -------------------------
   
            encode_txd[7:0]   <= xgmii_txd_d[7:0];   
            encode_txc[0]     <= xgmii_txc_d[0];   
            encode_txd[15:8]  <= xgmii_txd_d[15:8];   
            encode_txc[1]     <= xgmii_txc_d[1];   
            encode_txd[23:16] <= 8'h BC;   
            encode_txc[2]     <= 1'b 1;   
            encode_txd[31:24] <= 8'h BC;   
            encode_txc[3]     <= 1'b 1;   
            end
         else if (xgmii_termc[2] == 1'b 1 )
            begin

   // Termination on the Lane 2
   // -------------------------
   
            encode_txd[7:0]   <= xgmii_txd_d[7:0];   
            encode_txc[0]     <= xgmii_txc_d[0];   
            encode_txd[15:8]  <= xgmii_txd_d[15:8];   
            encode_txc[1]     <= xgmii_txc_d[1];   
            encode_txd[23:16] <= xgmii_txd_d[23:16];   
            encode_txc[2]     <= xgmii_txc_d[2];   
            encode_txd[31:24] <= 8'h BC;   
            encode_txc[3]     <= 1'b 1;   
            end
         else if (xgmii_termc[3] == 1'b 1 )
            begin

   // Termination on the Lane 3
   // -------------------------
   
            encode_txd[7:0]   <= xgmii_txd_d[7:0];   
            encode_txc[0]     <= xgmii_txc_d[0];   
            encode_txd[15:8]  <= xgmii_txd_d[15:8];   
            encode_txc[1]     <= xgmii_txc_d[1];   
            encode_txd[23:16] <= xgmii_txd_d[23:16];   
            encode_txc[2]     <= xgmii_txc_d[2];   
            encode_txd[31:24] <= xgmii_txd_d[31:24];   
            encode_txc[3]     <= xgmii_txc_d[3];   

   // No Termination
   // --------------
   
            end
         else if(xgmiii_seq == 1'b 1)
            begin
            encode_txd[31:0]  <= 32'h BCBCBCBC;
            encode_txc[3:0]   <= 4'b 1111;
            end
         else
            begin
            if(xgmii_txd_d[7:0] == 8'h 07 & xgmii_txc_d[0] == 1'b 1)
               begin
               encode_txd[7:0]  <= 8'h BC;   
               encode_txc[0]    <= 1'b 1;             
               end 
            else
               begin
               encode_txd[7:0]  <= xgmii_txd_d[7:0];   
               encode_txc[0]    <= xgmii_txc_d[0]; 
               end
            
            if(xgmii_txd_d[15:8] == 8'h 07 & xgmii_txc_d[1] == 1'b 1)
               begin
               encode_txd[15:8] <= 8'h BC;   
               encode_txc[1]    <= 1'b 1;             
               end 
            else
               begin
               encode_txd[15:8] <= xgmii_txd_d[15:8];   
               encode_txc[1]    <= xgmii_txc_d[1]; 
               end
            
            if(xgmii_txd_d[23:16] == 8'h 07 & xgmii_txc_d[2] == 1'b 1)
               begin
               encode_txd[23:16]<= 8'h BC;   
               encode_txc[2]    <= 1'b 1;             
               end 
            else
               begin
               encode_txd[23:16]<= xgmii_txd_d[23:16];   
               encode_txc[2]    <= xgmii_txc_d[2]; 
               end            
            if(xgmii_txd_d[31:24] == 8'h 07 & xgmii_txc_d[3] == 1'b 1)
               begin
               encode_txd[31:24]<= 8'h BC;   
               encode_txc[3]    <= 1'b 1;             
               end 
            else
               begin
               encode_txd[31:24]<= xgmii_txd_d[31:24];   
               encode_txc[3]    <= xgmii_txc_d[3]; 
               end              
            end
         end
      Q_COL,
      RANDOM_Q_COL:
         begin
         encode_txd[31:0] <= xgmii_txd_d[31:0];   
         encode_txc       <= 4'b 0001;   
         end
      A_COL,
      RANDOM_A_COL:
         begin
         encode_txd[31:0] <= 32'h 7C7C7C7C;   
         encode_txc       <= 4'b 1111;   
         end
      K_COL:
         begin
         encode_txd[31:0] <= 32'h BCBCBCBC;   
         encode_txc       <= 4'b 1111;   
         end
      RANDOM_K_COL:
         begin

        `ifdef MTIPXGXS_EEE_ENA

         case (lpi_sel)
                3'b 100:  {encode_txc, encode_txd} <= {4'b 1110, 32'h BCBCBCB4};   // D20.5
                3'b 101:  {encode_txc, encode_txd} <= {4'b 1101, 32'h BCBCB4BC};   // D20.5
                3'b 110:  {encode_txc, encode_txd} <= {4'b 1011, 32'h BCB4BCBC};   // D20.5
                3'b 111:  {encode_txc, encode_txd} <= {4'b 0111, 32'h B4BCBCBC};   // D20.5
                default:  {encode_txc, encode_txd} <= {4'b 1111, 32'h BCBCBCBC};
         endcase

        `else

         encode_txd[31:0] <= 32'h BCBCBCBC;   
         encode_txc       <= 4'b 1111;   

        `endif

         end
      RANDOM_R_COL:
         begin
        `ifdef MTIPXGXS_EEE_ENA

         case (lpi_sel)
                3'b 100:  {encode_txc, encode_txd} <= {4'b 1110, 32'h 1C1C1CB4};   // D20.5
                3'b 101:  {encode_txc, encode_txd} <= {4'b 1101, 32'h 1C1CB41C};   // D20.5
                3'b 110:  {encode_txc, encode_txd} <= {4'b 1011, 32'h 1CB41C1C};   // D20.5
                3'b 111:  {encode_txc, encode_txd} <= {4'b 0111, 32'h B41C1C1C};   // D20.5
                default:  {encode_txc, encode_txd} <= {4'b 1111, 32'h 1C1C1C1C};
         endcase
        
        `else

         encode_txd[31:0] <= 32'h 1C1C1C1C;   
         encode_txc       <= 4'b 1111;   

        `endif
        
         end

        default:
        begin
        // Any other case undefined (never reached)
        // ------------------------
         encode_txd[31:0] <= 32'h 1C1C1C1C;   
         encode_txc       <= 4'b 1111;   
        end
        
      endcase
      
         `ifdef USE_CLK_ENA
            end
         `endif     
      
      end
   end

endmodule // module pcs_tx_encoder